package cc.rengu.igas.channel.alipay.core.service.trans;

import cc.rengu.igas.channel.alipay.common.constant.AlipayConfigConstant;
import cc.rengu.igas.channel.alipay.common.constant.AlipayParamConstant;
import cc.rengu.igas.channel.alipay.common.constant.AlipayTreeNodeConstant;
import cc.rengu.igas.channel.alipay.common.enums.RespCodeEnum;
import cc.rengu.igas.channel.alipay.core.model.ChnlBizResponse;
import cc.rengu.igas.channel.alipay.core.service.base.AppAuthService;
import cc.rengu.igas.channel.alipay.facade.bean.AppAuthTokenInfo;
import cc.rengu.igas.channel.alipay.facade.request.AliGetAppAuthTokenRequest;
import cc.rengu.igas.channel.alipay.facade.response.AliGetAppAuthTokenResponse;
import cc.rengu.oltp.service.common.dao.CertInfoMapper;
import cc.rengu.oltp.service.common.dao.SecPlanInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.CertInfoMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.SecPlanInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.*;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.realize.SysParamService;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.util.ConvertUtil;
import cc.rengu.oltp.utility.util.StringUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;
import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AppTokenExchangeSubElement;
import com.alipay.api.request.AlipayOpenAuthTokenAppRequest;
import com.alipay.api.response.AlipayOpenAuthTokenAppResponse;

import java.util.*;

/**
 * 获取商户应用授权Token
 * Created by wangcheng on 2021/11/11 16:03
 */
public class AliGetAppAuthTokenService extends AppAuthService {
    @Override
    protected Object beforeBizProcess() throws Exception {
        AliGetAppAuthTokenRequest aliGetAppAuthTokenRequest = new AliGetAppAuthTokenRequest();
        ConvertUtil.convertOutput(aliGetAppAuthTokenRequest);
        return aliGetAppAuthTokenRequest;
    }

    @Override
    protected ChnlBizResponse callBizService(Object request) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        AliGetAppAuthTokenRequest aliGetAppAuthTokenRequest = (AliGetAppAuthTokenRequest) request;
        String instId = aliGetAppAuthTokenRequest.getHeader().getInstId();
        DstChannelCfg dstChannelCfg = (DstChannelCfg) xmlTreeUtil.getXmlTreeObjectValue(AlipayTreeNodeConstant.DST_CHANNEL_CFG, DstChannelCfg.class);
        AliGetAppAuthTokenResponse aliGetAppAuthTokenResponse = new AliGetAppAuthTokenResponse();
        aliGetAppAuthTokenResponse.setHeader(aliGetAppAuthTokenRequest.getHeader());

        /* 获取支付宝通讯配置参数 */
        SysParamService sysParamService = new SysParamServiceImpl();
        /*获取请求url*/
        SysParam sysParam = sysParamService.getSysParamInfo(instId, AlipayConfigConstant.ALIPAY_CONF_NODE, AlipayConfigConstant.ALIPAY_PAY_NET_URL);
        if (null == sysParam || StringUtil.isEmptyOrNull(sysParam.getParamValue())) {
            rglog.error("未配置支付宝直连专线URL地址，请配置");
            throw new BizException(RespCodeEnum.CONFIG_PARAM_NOT_EXIST.getRespCode(), RespCodeEnum.CONFIG_PARAM_NOT_EXIST.getRespDesc());
        }
        String requestUrl = sysParam.getParamValue();
        /*互联网代理IP*/
        sysParam = sysParamService.getSysParamInfo(instId, AlipayConfigConstant.ALIPAY_CONF_NODE, AlipayConfigConstant.ALIPAY_PROXY_NET_IP);
        String proxyIp = (null == sysParam || StringUtil.isEmptyOrNull(sysParam.getParamValue())) ? null : sysParam.getParamValue().trim();
        /*互联网代理端口*/
        sysParam = sysParamService.getSysParamInfo(instId, AlipayConfigConstant.ALIPAY_CONF_NODE, AlipayConfigConstant.ALIPAY_PROXY_NET_PORT);
        String proxyPort = (null == sysParam || StringUtil.isEmptyOrNull(sysParam.getParamValue())) ? null : sysParam.getParamValue().trim();
        /*报文类型*/
        sysParam = sysParamService.getSysParamInfo(instId, AlipayConfigConstant.ALIPAY_CONF_NODE, AlipayConfigConstant.ALIPAY_MSG_TYPE);
        String msgType = (null == sysParam || StringUtil.isEmptyOrNull(sysParam.getParamValue())) ? "json" : sysParam.getParamValue().trim();
        /*字符集*/
        sysParam = sysParamService.getSysParamInfo(instId, AlipayConfigConstant.ALIPAY_CONF_NODE, AlipayConfigConstant.ALIPAY_CHARSET);
        String charset = (null == sysParam || StringUtil.isEmptyOrNull(sysParam.getParamValue())) ? "UTF-8" : sysParam.getParamValue().trim();
        /*签名验签方式*/
        sysParam = sysParamService.getSysParamInfo(instId, AlipayConfigConstant.ALIPAY_CONF_NODE, AlipayConfigConstant.ALIPAY_SIGN_TYPE);
        String signType = (null == sysParam || StringUtil.isEmptyOrNull(sysParam.getParamValue())) ? "RSA2" : sysParam.getParamValue().trim();

        /* 根据通道安全计划获取安全计划 */
        String priKey = null;
        String pubKey = null;
        SecPlanInfoMapper secPlanInfoMapper = new SecPlanInfoMapperImpl();
        CertInfoMapper certInfoMapper = new CertInfoMapperImpl();
        List<SecPlanInfo> secPlanInfoList = secPlanInfoMapper.selectSecPlanInfoBySecPlanId(instId, dstChannelCfg.getSecPlanId());

        /* 获取签名验签证书（私钥） */
        Optional<SecPlanInfo> secPlanInfoOptSign = secPlanInfoList.stream().filter(item -> item.getSecPlanType().equals(AlipayParamConstant.SIGN_CERT_TYPE)).findFirst();
        if (secPlanInfoOptSign.isPresent()) {
            CertInfo certInfoPri = certInfoMapper.selectCertInfoByPrimaryKey(instId + secPlanInfoOptSign.get().getSecPlanId() + secPlanInfoOptSign.get().getSecPlanType());
            if (certInfoPri != null) {
                priKey = certInfoPri.getCertValue();
            }
        }

        /* 获取签名验签证书（公钥） */
        Optional<SecPlanInfo> secPlanInfoOpt = secPlanInfoList.stream().filter(item -> item.getSecPlanType().equals(AlipayParamConstant.VERIFY_CERT_TYPE)).findFirst();
        if (secPlanInfoOpt.isPresent()) {
            CertInfo certInfoPub = certInfoMapper.selectCertInfoByPrimaryKey(instId + secPlanInfoOpt.get().getSecPlanId() + secPlanInfoOpt.get().getSecPlanType());
            if (certInfoPub != null) {
                pubKey = certInfoPub.getCertValue();
            }
        }

        /* 调用支付宝开启代商户签约、创建应用事务 */
        rglog.debug("aliPayUrl = <{}>;appId = <{}>;priKey = <{}>;msgType = <{}>,charset = <{}>,pubKey = <{}>,signType = <{}>,proxyIp = <{}>,proxyPort = <{}>",
                requestUrl, dstChannelCfg.getAppId(), priKey, msgType, charset, pubKey, signType, proxyIp, proxyPort);
        AlipayClient alipayClient;
        if (StringUtil.isEmptyOrNull(proxyIp) || StringUtil.isEmptyOrNull(proxyPort)) {
            alipayClient = new DefaultAlipayClient(requestUrl, dstChannelCfg.getAppId(), priKey, msgType, charset, pubKey, signType);
        } else {
            alipayClient = new DefaultAlipayClient(requestUrl, dstChannelCfg.getAppId(), priKey, msgType, charset, pubKey, signType, proxyIp, proxyPort);
        }
        AlipayOpenAuthTokenAppRequest alipayOpenAuthTokenAppRequest = new AlipayOpenAuthTokenAppRequest();
        Map<String, String> authTokenMap = new HashMap<>();
        authTokenMap.put("grant_type", "authorization_code");
        authTokenMap.put("code", aliGetAppAuthTokenRequest.getAppAuthCode());
        alipayOpenAuthTokenAppRequest.setBizContent(JSON.toJSONString(authTokenMap));
        AlipayOpenAuthTokenAppResponse alipayOpenAuthTokenAppResponse = alipayClient.execute(alipayOpenAuthTokenAppRequest);
        if (alipayOpenAuthTokenAppResponse.isSuccess()) {
            List<AppTokenExchangeSubElement> appTokenList = alipayOpenAuthTokenAppResponse.getTokens();
            List<AppAuthTokenInfo> appAuthTokenInfoList = new ArrayList<>();
            appTokenList.forEach(item -> {
                AppAuthTokenInfo appAuthTokenInfo = new AppAuthTokenInfo();
                appAuthTokenInfo.setAppAuthToken(item.getAppAuthToken());
                appAuthTokenInfo.setAppRefreshToken(item.getAppRefreshToken());
                appAuthTokenInfo.setAuthAppId(item.getAuthAppId());
                appAuthTokenInfo.setExpiresIn(item.getExpiresIn());
                appAuthTokenInfo.setReExpiresIn(item.getReExpiresIn());
                appAuthTokenInfo.setUserId(item.getUserId());
                appAuthTokenInfoList.add(appAuthTokenInfo);
            });
            aliGetAppAuthTokenResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
            aliGetAppAuthTokenResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
            aliGetAppAuthTokenResponse.setAppAuthTokenInfoList(appAuthTokenInfoList);
        } else {
            aliGetAppAuthTokenResponse.setRespCode((null == alipayOpenAuthTokenAppResponse.getSubCode()) ? alipayOpenAuthTokenAppResponse.getCode() : alipayOpenAuthTokenAppResponse.getSubCode());
            aliGetAppAuthTokenResponse.setRespDesc((null == alipayOpenAuthTokenAppResponse.getSubMsg()) ? alipayOpenAuthTokenAppResponse.getMsg() : alipayOpenAuthTokenAppResponse.getSubMsg());
        }
        ChnlBizResponse chnlBizResponse = new ChnlBizResponse();
        chnlBizResponse.setResult(aliGetAppAuthTokenResponse);
        return chnlBizResponse;
    }

    @Override
    protected void afterBizProcess(ChnlBizResponse response) throws Exception {
        AliGetAppAuthTokenResponse aliGetAppAuthTokenResponse = (AliGetAppAuthTokenResponse) response.getResult();
        ConvertUtil.convertInput(aliGetAppAuthTokenResponse);
    }
}
